package com.efun.framework.autoconfigure;

import com.alibaba.druid.pool.DruidDataSource;
import org.beetl.sql.core.ClasspathLoader;
import org.beetl.sql.core.Interceptor;
import org.beetl.sql.core.NameConversion;
import org.beetl.sql.core.UnderlinedNameConversion;
import org.beetl.sql.core.db.DBStyle;
import org.beetl.sql.core.db.MySqlStyle;
import org.beetl.sql.ext.DebugInterceptor;
import org.beetl.sql.ext.spring4.BeetlSqlDataSource;
import org.beetl.sql.ext.spring4.BeetlSqlFactoryBean;
import org.beetl.sql.ext.spring4.BeetlSqlScannerConfigurer;
import org.beetl.sql.ext.spring4.SqlManagerFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;

/**
 * beetlsql的自动配置
 * @author kinven on 17-7-29.
 */
@Configuration
@ConditionalOnClass(BeetlSqlFactoryBean.class)
@ConditionalOnMissingBean(BeetlSqlFactoryBean.class)
@EnableConfigurationProperties({BeetlsqlProperties.class,DruidProperties.class})
public class BeetlsqlAutoConfiguration {

    @Autowired
    private BeetlsqlProperties beetlsqlProperties;

    @Autowired
    private DruidProperties druidProperties;

    /**
     * DataSource 从数据源配置
     * @return
     */
    @ConfigurationProperties(prefix = "efun.datasource.read")
    @Bean(name = "readDataSource")
    public DataSource readDruidDataSource() throws SQLException {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setConnectProperties(druidProperties.connectProperties());
        druidDataSource.setFilters(druidProperties.getFilters());
        return druidDataSource;
    }
    /**
     * DataSource 主数据源配置
     * @return
     */
    @ConfigurationProperties(prefix = "efun.datasource.write")
    @Bean(name = "writeDataSource")
    @Primary
    public DataSource writeDruidDataSource() throws SQLException {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setConnectProperties(druidProperties.connectProperties());
        druidDataSource.setFilters(druidProperties.getFilters());
        return druidDataSource;
    }

    @Bean(name="txManager")
    public DataSourceTransactionManager getDataSourceTransactionManager(@Qualifier("writeDataSource") DataSource datasource) {
        DataSourceTransactionManager dsm = new DataSourceTransactionManager();
        dsm.setDataSource(datasource);
        return dsm;
    }

    @Bean(name="beetlSqlScannerConfigurer")
    public BeetlSqlScannerConfigurer beetlSqlScannerConfigurer() {
        BeetlSqlScannerConfigurer conf = new BeetlSqlScannerConfigurer();
        conf.setBasePackage(beetlsqlProperties.getBasePackage());
        conf.setDaoSuffix(beetlsqlProperties.getDaoSuffix());
        conf.setSqlManagerFactoryBeanName("sqlManagerFactoryBean");
        return conf;
    }


    @Bean
    public BeetlSqlDataSource beetlSqlDataSource(@Qualifier("writeDataSource") DataSource writeDatasource, @Qualifier("readDataSource") DataSource readDatasource){
        BeetlSqlDataSource source = new BeetlSqlDataSource();
        source.setMasterSource(writeDatasource);
        source.setSlaves(new DataSource[]{readDatasource});
        return source;
    }


    @Bean
    public NameConversion underlinedNameConversion(){
        return new UnderlinedNameConversion();
    }

    @Bean
    public ClasspathLoader classpathLoader(){
        return new ClasspathLoader(beetlsqlProperties.getSqlLoaderPath());
    }


    /**
     * 默认使用Debug拦截器打印SQL。
     * @param beetlSqlDataSource
     * @param nameConversion
     * @param classpathLoader
     * @return
     */
    @Bean(name="sqlManagerFactoryBean")
    @Primary
    public SqlManagerFactoryBean sqlManagerFactoryBean(
            BeetlSqlDataSource beetlSqlDataSource,
            NameConversion nameConversion,
            ClasspathLoader classpathLoader) {
        SqlManagerFactoryBean factory = new SqlManagerFactoryBean();
        factory.setCs(beetlSqlDataSource);
        factory.setDbStyle(getDbStyle());
        factory.setInterceptors(getInterceptors());
        factory.setNc(nameConversion);
        factory.setSqlLoader(classpathLoader);
        return factory;
    }

    /**
     * 目前默认使用mysql数据库,未来扩展数据库时候进行更改.
     * 如果接入其他数据库，请自行修改
     * @return
     */
    protected DBStyle getDbStyle() {
        DBStyle dbStyle = new MySqlStyle();
        if(beetlsqlProperties.getDbStyle().equalsIgnoreCase("mysql")){
            return new MySqlStyle();
        }
        return dbStyle;
    }

    /**
     * 目前只能有debugInterceptor，其他的未来需要切换框架或者增加功能时候进行扩展,
     * @return
     */
    protected Interceptor[] getInterceptors(){
        String[] strInterceptors = beetlsqlProperties.getInterceptors().split("\\,");
        ArrayList<Interceptor> listInterceptors = new ArrayList<Interceptor>();
        for(String strInterceptor : strInterceptors){
            if(strInterceptor.equalsIgnoreCase("debugInterceptor")){
                listInterceptors.add(new DebugInterceptor());
            }
        }
        return listInterceptors.toArray(new Interceptor[]{});
    }


}
